package com.hup.sidebar.framework.model;

import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;

import com.alibaba.fastjson.JSONArray;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;
import java.util.List;

/**
 * SharedPreferences 持久化的字段,工具类
 *
 * @author hugan
 * @date 2025/11/13
 */
public interface SpFieldHandler {

    void init(String fieldName, Field field, SpField spField);

    /**
     * 从 SharedPreferences 中读取字段并赋值, 处理缺省值
     */
    void load(Object target, SharedPreferences sp) throws IllegalAccessException;

    Object getDefault();

    Object get(Object target) throws IllegalAccessException;

    /**
     * 赋值
     */
    void set(Object target, Object value) throws IllegalAccessException;

    /**
     * 赋值&保存
     */
    void set(Object target, Object value, SharedPreferences sp) throws IllegalAccessException;

    /**
     * 批量[赋值&保存], 注意最后要调用 Editor.apply
     *
     * @param editor android.content.SharedPreferences#edit()
     */
    void batchSet(Object target, Object value, Editor editor) throws IllegalAccessException;

    /**
     * 重置
     */
    void reset(Object target) throws IllegalAccessException;

    /**
     * 重置&保存
     */
    void reset(Object target, SharedPreferences sp) throws IllegalAccessException;

    /**
     * 用SharedPreferences 持久化的字段
     */
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    @interface SpField {
        int defInt() default 0;

        boolean defBoolean() default false;

        String defString() default "";

        Class<?> listItemClz() default int.class;

        Class<? extends SpFieldHandler> handler();
    }

    class SpIntHandler implements SpFieldHandler {
        protected String fieldName;
        protected Field field;
        protected int defValue;

        @Override
        public void init(String fieldName, Field field, SpField spField) {
            this.fieldName = fieldName;
            this.field = field;
            field.setAccessible(true);
            defValue = spField.defInt();
        }

        @Override
        public void load(Object target, SharedPreferences sp) throws IllegalAccessException {
            field.setInt(target, sp.getInt(fieldName, defValue));
        }

        @Override
        public Object getDefault() {
            return defValue;
        }

        @Override
        public Object get(Object target) throws IllegalAccessException {
            return field.get(target);
        }

        @Override
        public void set(Object target, Object value) throws IllegalAccessException {
            field.setInt(target, (int) value);
        }

        @Override
        public void set(Object target, Object value, SharedPreferences sp) throws IllegalAccessException {
            field.setInt(target, (int) value);
            sp.edit().putInt(fieldName, (int) value).apply();
        }

        @Override
        public void batchSet(Object target, Object value, Editor editor) throws IllegalAccessException {
            field.setInt(target, (int) value);
            editor.putInt(fieldName, (int) value);
        }

        @Override
        public void reset(Object target) throws IllegalAccessException {
            field.setInt(target, defValue);
        }

        @Override
        public void reset(Object target, SharedPreferences sp) throws IllegalAccessException {
            field.setInt(target, defValue);
            sp.edit().putInt(fieldName, defValue).apply();
        }
    }

    class SpBooleanHandler implements SpFieldHandler {
        protected String fieldName;
        protected Field field;
        protected boolean defValue;

        @Override
        public void init(String fieldName, Field field, SpField spField) {
            this.fieldName = fieldName;
            this.field = field;
            field.setAccessible(true);
            defValue = spField.defBoolean();
        }

        @Override
        public void load(Object target, SharedPreferences sp) throws IllegalAccessException {
            field.setBoolean(target, sp.getBoolean(fieldName, defValue));
        }

        @Override
        public Object getDefault() {
            return defValue;
        }

        @Override
        public Object get(Object target) throws IllegalAccessException {
            return field.get(target);
        }

        @Override
        public void set(Object target, Object value) throws IllegalAccessException {
            field.setBoolean(target, (boolean) value);
        }

        @Override
        public void set(Object target, Object value, SharedPreferences sp) throws IllegalAccessException {
            field.setBoolean(target, (boolean) value);
            sp.edit().putBoolean(fieldName, (boolean) value).apply();
        }

        @Override
        public void batchSet(Object target, Object value, Editor editor) throws IllegalAccessException {
            field.setBoolean(target, (boolean) value);
            editor.putBoolean(fieldName, (boolean) value);
        }

        @Override
        public void reset(Object target) throws IllegalAccessException {
            field.setBoolean(target, defValue);
        }

        @Override
        public void reset(Object target, SharedPreferences sp) throws IllegalAccessException {
            field.setBoolean(target, defValue);
            sp.edit().putBoolean(fieldName, defValue).apply();
        }
    }

    class SpStringHandler implements SpFieldHandler {
        protected String fieldName;
        protected Field field;
        protected String defValue;

        @Override
        public void init(String fieldName, Field field, SpField spField) {
            this.fieldName = fieldName;
            this.field = field;
            field.setAccessible(true);
            defValue = spField.defString();
        }

        @Override
        public void load(Object target, SharedPreferences sp) throws IllegalAccessException {
            field.set(target, sp.getString(fieldName, defValue));
        }

        @Override
        public Object getDefault() {
            return defValue;
        }

        @Override
        public Object get(Object target) throws IllegalAccessException {
            return field.get(target);
        }

        @Override
        public void set(Object target, Object value) throws IllegalAccessException {
            field.set(target, value);
        }

        @Override
        public void set(Object target, Object value, SharedPreferences sp) throws IllegalAccessException {
            field.set(target, value);
            sp.edit().putString(fieldName, (String) value).apply();
        }

        @Override
        public void batchSet(Object target, Object value, Editor editor) throws IllegalAccessException {
            field.set(target, value);
            editor.putString(fieldName, (String) value);
        }

        @Override
        public void reset(Object target) throws IllegalAccessException {
            field.set(target, defValue);
        }

        @Override
        public void reset(Object target, SharedPreferences sp) throws IllegalAccessException {
            field.set(target, defValue);
            sp.edit().putString(fieldName, defValue).apply();
        }
    }

    class SpStringListHandler extends SpStringHandler {
        protected Class<?> itemClz;

        @Override
        public void init(String fieldName, Field field, SpField spField) {
            super.init(fieldName, field, spField);
            itemClz = spField.listItemClz();
        }

        @Override
        public void load(Object target, SharedPreferences sp) throws IllegalAccessException {
            String str = sp.getString(fieldName, defValue);
            List<?> list = JSONArray.parseArray(str, itemClz);
            field.set(target, list);
        }

        @Override
        public Object get(Object target) throws IllegalAccessException {
            return field.get(target);
        }

        @Override
        public void set(Object target, Object value) throws IllegalAccessException {
            field.set(target, value);
        }

        @Override
        public void set(Object target, Object value, SharedPreferences sp) throws IllegalAccessException {
            throw new IllegalAccessException("代码异常");
        }

        @Override
        public void batchSet(Object target, Object value, Editor editor) throws IllegalAccessException {
            field.set(target, value);
            String str = JSONArray.toJSONString(value);
            editor.putString(fieldName, str);
        }

        @Override
        public void reset(Object target) throws IllegalAccessException {
            List<?> list = JSONArray.parseArray(defValue, itemClz);
            field.set(target, list);
        }

        @Override
        public void reset(Object target, SharedPreferences sp) throws IllegalAccessException {
            throw new IllegalAccessException("代码异常");
        }
    }

}